home *** CD-ROM | disk | FTP | other *** search
-
- ; IMPORTANT NOTE
- ; --------------
-
- ; This source code is given AS IT IS to the Amiga community, following
- ; a suggestion from Hans Guijt. Explicit permission is given to use it for
- ; any non-profit purpose, either in parts or as a whole, without any
- ; further permission from the author. The author himself reserves the right
- ; to use this source code at any time in the future again. For commercial
- ; use of this source code, prior written permission from the auther is
- ; required.
-
-
- ; Contact electronic mail addresses: grimm@particle.phys.ethz.ch
- ; oliver.grimm@desy.de
-
- ; Postal address: Oliver Grimm
- ; Steinbecker Str. 69
- ; 21244 Buchholz
-
- ; Germany
-
-
- ; (Addresses as of March 1999)
-
-
- ; FASTPRIM was written in 1989/1991/1993 by Oliver Grimm
-
- ;
- ; Programmentwicklung:
- ;
- ; V1.0 (? 1989) - erste Version
- ; V1.1 (April 1991) - Device-Handling
- ; V1.2 (August 1993) - Bit-Modell; Byte-Modell ca. 15 % schneller;
- ; Zeitmessung; Zählroutine; schnelles Ctrl-c;
- ; variabler Ausgabebeginn; gepufferte Speicherroutine
- ; V1.3 (Sept. 1994) - Versionsinformation; Datei wird sofort geöffnet
-
-
- SysBase = 4
-
- LVOOpenLibrary = -552
- LVOCloseLibrary = -414
- LVOAllocMem = -198
- LVOFreeMem = -210
- LVOFindTask = -294
- LVOSetExcept = -312
-
- LVOWrite = -48
- LVORead = -42
- LVOOpen = -30
- LVOClose = -36
- LVOOutput = -60
- LVODelay = -198
- LVODateStamp = -192
-
- WRITEBUF = 1000 ; Länge des Schreib-Puffers
-
-
- ; Kommandozeile auswerten
-
- cmp.b #'-',(a0) ; wird Bit-Modell erzwungen ?
- bne.s noBitForce
- move.b #1,Method
- lea 1(a0),a0
-
- noBitForce:
- bsr GetNum ; Primzahlen bis wohin berechnen ?
- move.l d3,Max
-
- bsr SkipSpace
-
- bsr GetNum ; Ausgabebeginn einlesen wenn vorhanden
- move.l d3,FirstOut
-
- cmp.l #1,FirstOut ; FirstOut mindestens 2
- bhi.s FirstOK
- move.l #2,FirstOut
-
- FirstOK:
- bsr SkipSpace
-
- cmp.b #10,(a0) ; Filename angegeben ?
- beq.s noFilename
-
- move.l a0,Filename
- FindLF:
- cmp.b #10,(a0)+ ; Linefeed in Null umwandeln
- bne.s FindLF
- move.b #0,-1(a0)
-
- noFilename:
- move.l SysBase,a6 ; eigenen Task finden
- sub.l a1,a1
- jsr LVOFindTask(a6)
- move.l d0,Task ; in ReplyPort eintragen
-
- ;move.l d0,a0 ; wenn mit RUN gestartet, Abbruch
- ;move.l 172(a0),d0
- ;asl.l #2,d0 ; BCPL-Zeiger
- ;move.l d0,a0
- ;move.l 44(a0),d0
- ;beq.s noRun
-
- ;moveq #20,d2 ; Rückgabewert in die Shell
- ;bra Quit
-
-
- ; dos.library öffnen und Ausgabe-Handle besorgen
-
- noRun:
- moveq #20,d2 ; nochmal Rückgabewert, falls dos.library
- lea DosName(pc),a1 ; öffnen nicht möglich
- moveq #0,d0
- jsr LVOOpenLibrary(a6)
- move.l d0,DosBase
- beq Quit
-
- move.l DosBase(pc),a6 ; Ausgabe-Handle ins Fenster
- jsr LVOOutput(a6)
- move.l d0,Handle
- beq noHandle
-
- move.l Task(pc),a0
- move.l 42(a0),OldExceptCode ; alten Exceptionzeiger sichern
- move.l #ExceptCode,42(a0) ; neuen eintagen
-
- move.l SysBase,a6
- move.l #4096,d0 ; Execptions bei CTRL-c an
- move.l d0,d1
- jsr LVOSetExcept(a6)
-
- ; Haupt-Programm
-
- cmp.l #1,Max ; wurde überhaupt eine Zahl größer 1 angegeben ?
- bhi.s CommOK
- move.l #UsageText,Error
- bra noMemory
-
- CommOK:
- move.l #MemoryErr,Error
- move.l Max(pc),d0
- add.l #8,d0
- move.l d0,MemLen
-
- tst.b Method
- bne.s Bit_forced
-
- move.l SysBase,a6 ; Speicher allokieren
- move.l MemLen(pc),d0
- move.l #65536,d1 ; mit Null initialisieren
- jsr LVOAllocMem(a6)
- move.l d0,Memory
- bne.s GotMem
-
- Bit_forced:
- move.b #1,Method ; nicht genug Speicher für Quick-Calc
- move.l SysBase,a6 ; oder Bit-Modell erzwungen
- move.l MemLen(pc),d0
- asr.l #3,d0
- move.l d0,MemLen
- move.l #65536,d1
- jsr LVOAllocMem(a6)
- move.l d0,Memory
- beq noMemory
-
-
- GotMem:
- move.l #WRITEBUF,d0 ; Save-Puffer allokieren
- move.l #65536,d1
- jsr LVOAllocMem(a6)
- move.l d0,SaveBuf
- beq noBufMem
-
- clr.l Error ; Errorstatus auf Null setzen
- move.l #StartText,d2
- bsr Print
-
-
- tst.l Filename ; Primzahlen speichern ?
- beq.s BeginnCalc
-
- move.l DosBase(pc),a6 ; dann Datei schon jetzt öffnen
- move.l Filename(pc),d1
- move.l #1006,d2
- jsr LVOOpen(a6)
- move.l d0,FileHandle
- bne.s BeginnCalc
-
- move.l #OpenErr,d2
- bsr Print
- clr.l Filename
-
-
- BeginnCalc:
- bsr GetTime ; Zeitmessung starten
- move.l d0,Time
- tst.b Method
- bne.s Slow
-
- move.l #FastText,d2 ; Byte-Modell
- bsr Print
- bsr QuickCalc
- bra.s Fertig
-
- Slow:
- move.l #SlowText,d2 ; Bit-Modell
- bsr Print
- bsr MemCalc
-
- Fertig:
- bsr GetTime
- sub.l Time(pc),d0
- add.l #25,d0
- divu #50,d0
- ext.l d0
- move.l d0,Time
-
- tst.b Flag ; Berechnung abgebrochen ?
- beq.s noAbort
-
- move.l #AbortText,d2
- bsr Print
- bra CloseAll
-
-
- noAbort:
- move.l #ReadyText,d2
- bsr Print
-
- move.l #End_of_Count,AbortAdr
- move.l Memory(pc),a2 ; Primzahlen zählen
- moveq #1,d2
- move.l Max(pc),d4
- moveq #0,d5
- tst.b Method
- bne.s CountMem
-
- lea 2(a2),a0
- add.l Max(pc),a2
-
- CountQuick:
- cmp.l a2,a0
- bhi.s End_of_Count
-
- tst.b (a0)+
- bne.s CountQuick
- addq.l #1,d5
- bra.s CountQuick
-
- CountMem:
- addq.l #1,d2
- cmp.l d4,d2
- bhi.s End_of_Count
-
- move.l d2,d0 ; Bytenummer
- asr.l #3,d0
- move.b d2,d1 ; Bitnummer
- and.b #7,d1
-
- bne.s noSkip ; wenn Bitnummer 0 und ganzes Byte ist $ff,
- cmp.b #$ff,0(a2,d0.l) ; dann 8 Positionen überspringen, da keine
- bne.s noSkip ; Primzahl in diesem Byte
- addq.l #7,d2
- bra.s CountMem
-
- noSkip:
- btst.b d1,0(a2,d0.l)
- bne.s CountMem
- addq.l #1,d5
- bra.s CountMem
-
- End_of_Count:
- clr.l AbortAdr
- move.l d5,PrimeNum ; Anzahl sichern
-
- move.b Flag(pc),CountFlag
- bne.s CountOK
- lea CountText(pc),a2
- bsr PrintNum
-
- CountOK:
- move.l #CountText,d2
- bsr Print
- clr.b Flag
-
- Save:
- tst.l Filename ; Primzahlen speichern ?
- beq.s noSave
-
- move.l #SaveText,d2
- bsr Print
-
- moveq #0,d6 ; Primzahlen speichern
- bsr WritePrim
-
- move.l #SaveAbText,d2 ; Text Aborted/Done ausgeben
- tst.b Flag
- bne.s notDone
- move.l #DoneText,d2
- notDone:
- bsr Print
-
- noSave:
- clr.b Flag
- moveq #1,d6 ; Primzahlen auf Screen ausgeben
- bsr WritePrim
-
-
- ; alle Resourcen wieder schließen
-
- End_of_Output:
- lea EndText+56(pc),a2 ; Anzahl/Zeit ausgeben
- move.l Time(pc),d5 ; wenn 0, dann 'less than 1' ausgeben
- beq.s tooShort
- bsr PrintNum
- tooShort:
- tst.b CountFlag ; falls nicht gezählt, nur Zeit ausgeben
- bne.s noCount
- lea EndText+20(pc),a2
- move.l PrimeNum(pc),d5
- bsr PrintNum
- noCount:
- move.l #EndText,d2
- bsr Print
-
- CloseAll:
- tst.l FileHandle
- beq.s noFile_to_close
-
- move.l DosBase(pc),a6 ; Datei schließen
- move.l FileHandle(pc),d1
- jsr LVOClose(a6)
-
- noFile_to_close:
- move.l SysBase,a6
- move.l SaveBuf(pc),a1
- move.l #WRITEBUF,d0
- jsr LVOFreeMem(a6)
-
- noBufMem:
- move.l Memory(pc),a1
- move.l MemLen(pc),d0
- jsr LVOFreeMem(a6)
-
- noMemory:
- move.l Error(pc),d2 ; eventuell Fehlermeldung/Usage-Text ausgeben
- beq.s noError
- bsr Print
-
- noError:
- move.l SysBase,a6
- moveq #0,d0 ; Exceptions wieder aus
- move.l #4096,d1
- jsr LVOSetExcept(a6)
- move.l Task(pc),a0 ; alter Exceptionzeiger
- move.l OldExceptCode(pc),42(a0)
-
- moveq #0,d2 ; Rückgabe in Shell: kein Fehler
-
- noHandle:
- move.l SysBase,a6
- move.l DosBase(pc),a1
- jsr LVOCloseLibrary(a6)
-
- Quit:
- move.l d2,d0 ; Rückgabewert ins richtige Register
- rts
-
- ;
- ; ------------------------ Subroutinen ----------------------------
- ;
-
- ; Die Zahl, deren ASCII-Darstellung ab der Adresse aus a0 steht, wird
- ; in d3 zurückgegeben; a0 zeigt auf das erste Zeichen nach der Zahl
-
-
- GetNum:
- moveq #0,d3
-
- GetLoop:
- moveq #0,d2
- move.b (a0)+,d2
- sub.b #'0',d2
- bmi.s noNumber
- cmp.b #9,d2
- bhi.s noNumber
-
- move.l d3,d1 ; 'mulu #10,d3', aber mehr als 16 Bit benötigt
- asl.l #2,d1
- add.l d1,d3
- add.l d3,d3
-
- add.l d2,d3
- bra.s GetLoop
-
- noNumber:
- lea -1(a0),a0
- rts
-
-
- ; Die Zahl in d5 wird nach Adresse a2 geschrieben; mit Tab am Ende
-
- PrintNum:
- move.l d5,d2
- lea 1(a2),a1
- moveq #9,d1
- lea Table(pc),a0
-
- NextDigit:
- moveq #"0",d0
- Dec1:
- addq.b #1,d0
- sub.l (a0),d2
- bcc.s Dec1
- subq.b #1,d0
- add.l (a0),d2
- move.b d0,(a1)+
- lea 4(a0),a0
- dbra d1,NextDigit
-
- move.l a2,a0
- noZero:
- move.b #" ",(a0)+ ; führende Nullen löschen
- cmp.b #"0",(a0)
- beq.s noZero
- rts
-
-
- ; Textausgabe, in d2 Zeiger auf den Text
-
- Print:
- move.l DosBase(pc),a6
- move.l Handle(pc),d1
- moveq #0,d3
- move.l d2,a0
-
- Count:
- addq.l #1,d3
- tst.b (a0)+
- bne.s Count
- subq.l #1,d3
- jsr LVOWrite(a6)
- rts
-
-
- ; WritePrim gibt alle Primzahlen aus. Ist d6 Null in eine Datei, sonst auf
- ; den Bildschirm
-
- WritePrim:
- move.l Memory(pc),a3
- clr.l BufCnt
- move.l FirstOut(pc),d5
- subq.l #1,d5
-
- WriteLoop:
- addq.l #1,d5
- cmp.l Max(pc),d5
- bhi.s End_of_Write
-
- tst.b Method
- bne.s MemMethod
-
- tst.b 0(a3,d5.l)
- bra.s Check
-
- MemMethod:
- move.l d5,d0 ; Bytenummer
- asr.l #3,d0
- move.b d5,d1 ; Bitnummer
- and.b #7,d1
- btst.b d1,(a3,d0.l)
-
- Check:
- bne.s WriteLoop ; wenn Byte bzw. Bit Null, dann Primzahl
-
- tst.b Flag ; Ctrl-c gedrückt ?
- bne.s End_of_Write
- tst.b d6 ; Screen oder Datei ?
- bne.s Screen
-
- move.l BufCnt(pc),d0
- move.l SaveBuf(pc),a0
- move.l d5,0(a0,d0.l) ; d5 in Puffer schreiben
-
- addq.l #4,BufCnt
- cmp.l #WRITEBUF-6,BufCnt ; Puffer voll ?
- bls.s WriteLoop
- bsr StoreBuf ; dann sichern
- bra.s WriteLoop
-
- Screen:
- lea Buffer(pc),a2 ; Primzahl in d5 in Shell ausgeben
- bsr PrintNum
- move.l #Buffer+1,d2
- bsr Print
-
- bra.s WriteLoop
-
- End_of_Write:
- tst.b d6 ; in Datei, dann restlichen Puffer sichern
- bne.s noBufFlush
- tst.l BufCnt
- beq.s noBufFlush
- bsr StoreBuf
-
- noBufFlush:
- rts
-
-
- StoreBuf:
- move.l DosBase(pc),a6 ; Puffer sichern und Zähler zurücksetzen
- move.l FileHandle(pc),d1
- move.l SaveBuf(pc),d2
- move.l BufCnt(pc),d3
- jsr LVOWrite(a6)
-
- clr.l BufCnt
- rts
-
-
- ; GetTime übergibt in d0 die Systemzeit in 1/50 Sekunden
-
- GetTime:
- move.l DosBase(pc),a6
- move.l #TimeBuf,d1
- jsr LVODateStamp(a6)
-
- move.l TimeBuf(pc),d2
- mulu #24*60,d2 ; Tage in Minuten umrechnen
- add.l TimeBuf+4(pc),d2 ; Minuten des Tages addieren
- moveq #0,d0
- move.l #2999,d1
- Min_to_Tick:
- add.l d2,d0 ; Minuten in Ticks wandeln (*60*50)
- dbra d1,Min_to_Tick
- add.l TimeBuf+8(pc),d0 ; Ticks addiereen
- rts
-
-
- ; SkipSpace überspingt alle Spaces,Tabs,Shift-Spaces ab Adresse a0
-
- SkipSpace:
- lea 1(a0),a0
- cmp.b #32,-1(a0) ; Space
- beq.s SkipSpace
- cmp.b #160,-1(a0) ; Shift-Space
- beq.s SkipSpace
- cmp.b #9,-1(a0) ; Tab
- beq.s SkipSpace
-
- lea -1(a0),a0
- rts
-
-
- ; Exception-Handler wird aufgerufen, wenn CTRL-c gedrückt
-
- ExceptCode:
- move.l AbortAdr(pc),d1 ; Rücksprungadresse in Task ändern,
- beq.s noAdress ; wenn gewünscht
- move.l Task(pc),a0
- move.l 54(a0),a0 ; Zeiger auf Stack
- move.l d1,(a0) ; PC ändern
- noAdress:
- move.b #1,Flag
- rts
-
-
- ;
- ; --- Es folgen die beiden Berechnungsroutinen ---
- ;
-
- ; 1.) maximale Geschwindigkeit
-
- QuickCalc:
- move.l #QuickEnd,AbortAdr ; für Exception
-
- move.l Memory(pc),a0
- move.l Max(pc),d2
- move.l a0,a2
- add.l d2,a2 ; oberes Ende der Liste
- moveq #2,d0
-
- QuickWeiter:
- move.l d0,d1
- mulu d1,d1
- cmp.l d2,d1
- bhi.s QuickEnd ; Algorithmus beenden
-
- move.l a0,a1 ; alle nicht-Primzahlen markieren
- add.l d0,a1
- bra.s QuickLab
- QuickLoop:
- move.b #1,(a1)
- QuickLab:
- add.l d0,a1
- cmp.l a2,a1
- bls.s QuickLoop
-
- QuickSuche:
- addq.l #1,d0
- tst.b 0(a0,d0.l)
- bne.s QuickSuche
- bra.s QuickWeiter
-
- QuickEnd:
- clr.l AbortAdr
- rts
-
- ; 2.) Speichersparend ; benötigt nur 1/8 des Speicherplatzes
-
- MemCalc:
- move.l #QuickEnd,AbortAdr
-
- move.l Memory(pc),a0
- move.l Max(pc),d2
- moveq #2,d0
-
- MemWeiter:
- move.l d0,d1
- mulu d1,d1
- cmp.l d2,d1
- bhi.s QuickEnd ; Algorithmus beenden
-
- move.l d0,d1 ; alle nicht-Primzahlen markieren
- bra.s MemLab
-
- MemLoop:
- move.l d1,d4 ; Bytenummer
- asr.l #3,d4
- move.b d1,d3 ; Bitnummer
- and.b #7,d3
- bset.b d3,(a0,d4.l)
- MemLab:
- add.l d0,d1
- cmp.l d2,d1
- bls.s MemLoop
-
- MemSuche:
- addq.l #1,d0
- move.l d0,d1
- asr.l #3,d1
- move.b d0,d3
- and.b #7,d3
- btst.b d3,0(a0,d1.l)
- bne.s MemSuche
- bra.s MemWeiter
-
-
- ;
- ; --- Datenbreich ---
- ;
-
- Version: dc.b "$VER: FastPrim 1.3 (9.9.1994)",0
-
-
- DosName: dc.b "dos.library",0
-
- StartText:
- dc.b 10,$9b,"33;1mFASTPRIM V1.3"
- dc.b $9b,"0;33m by Oliver Grimm",10
- dc.b "Written 1989-1994 - All rights reserved.",$9b,"0m",10,10,0
-
- FastText:
- dc.b "Calculating prime numbers using fast byte model ...",10
- dc.b "Press Ctrl-c to abort.",10,10,0
-
- SlowText:
- dc.b "Calculating prime numbers using memory-efficient bit model ...",10
- dc.b "Press Ctrl-c to abort.",10,10,0
-
- UsageText:
- dc.b 10,$9b,"1mUsage:",$9b,"22m Fastprim",$9b,"33m [-]Number [Number] [Filename]",$9b,"0m",10,10
- dc.b "Parameters in [] are optional.",10
- dc.b "The first number determines the upper limit of calculation, the optional",10
- dc.b "minus sign forces the use of the bit model (see doc file). Output will",10
- dc.b "begin with the first prime number equal or higher than the second number.",10
- dc.b "Furthermore, prime numbers can be stored in the file given by FILENAME.",10,10,0
-
- ReadyText: dc.b "Calculation complete - Number of Prime's:",0
- CountText: dc.b " ------- ",10,10,0
-
- EndText: dc.b 10,10,"Number of Prime's: ------- Calculation time: less than 1 s",10,10,0
- AbortText: dc.b 10,10," --- Calculation terminated ---",10,10,0
-
- SaveText: dc.b "Writing prime numbers to file ... ",0
- DoneText: dc.b "Done.",10,10,0
- SaveAbText: dc.b "Aborted.",10,10,0
-
-
- OpenErr: dc.b "Unable to open file, no prime numbers will be stored.",10,10,10,0
- MemoryErr: dc.b "Error: Insufficient free store",10,10,0
- DeviceErr: dc.b "Error: Unable to open input device",10,10,0
- HandlerErr: dc.b "Error: Unable to install input handler",10,10,0
-
-
- Method: dc.b 0 ; Null, wenn QuickCalc
- Flag: dc.b 0 ; Ctrl-c Handler-Flag
- CountFlag: dc.b 0 ; Endtext unterdrücken, falls zählen nicht fertig
-
- even
-
- Task: dc.l 0
- DosBase: dc.l 0
- OldExceptCode: dc.l 0
- Handle: dc.l 0
-
- Memory: dc.l 0 ; Zeiger auf Primzahl-Speicher
- MemLen: dc.l 0 ; dessen Länge
- SaveBuf: dc.l 0 ; Puffer für Save-Funktion
- BufCnt: dc.l 0 ; aktuelle Position in Puffer
-
- Filename: dc.l 0 ; Zeiger auf Filenamen, wenn Speichern gewünscht
- FileHandle: dc.l 0
-
- Buffer: ds.b 11 ; für Primzahl-Ausgabe
- dc.b 9,0 ; Tabulator
-
- TimeBuf: ds.l 3 ; für DateStamp
- Time: dc.l 0
-
- Max: dc.l 0 ; Primzahl-Obergrenze
- FirstOut: dc.l 0
- PrimeNum: dc.l 0 ; Anzahl der Primzahlen
-
- AbortAdr: dc.l 0 ; Zieladresse bei Ctrl-c
- Error: dc.l 0 ; Adresse des Fehlertextes oder NULL
-
- Table:
- dc.l 1000000000
- dc.l 100000000
- dc.l 10000000
- dc.l 1000000
- dc.l 100000
- dc.l 10000
- dc.l 1000
- dc.l 100
- dc.l 10
- dc.l 1